//
// Created by yasin on 2024/9/5.
//

#ifndef WEBRTC_CLIENT__SIGNALING_CLIENT_H_
#define WEBRTC_CLIENT__SIGNALING_CLIENT_H_

#include <string>
#include <functional>

#include "rtc_client/rtc_wrapper.h"
#include "web_socket_client.h"
#include "nlohmann/json.hpp"
#include "api/peer_connection_interface.h"

namespace rtc {
  class Thread;
}

namespace ohosrtc {

struct IceServer {
  std::string url;
  std::string username;
  std::string passwd;
};

struct RoomAccessInfo {
  std::vector<IceServer> ice_servers;
  std::vector<std::string> room_messages;
  std::string client_id;
  std::string wss_url;
  std::string wss_post_url;
  bool is_initiator = false;
};

enum class ConnectionState {
  Disconnected,
  HttpJoined,
  WebSocketConnected,
  SignalingConnected
};

using SignalHandler = std::function<void(const std::string &)>;

template<typename... Args>
using SuccessCallback = std::function<void(Args ...)>;


using FailCallback = std::function<void(const std::string &)>;
using RemoteSdpHandler = std::function<void(SDP *)>;
using RemoteIceCandidateHandler = std::function<void(IceCandidate *)>;
using RemoteByeHandler = std::function<void()>;

class SignalingClient {
 public:
  SignalingClient();
  //connect to calling room
  void Connect(const std::string &url, const std::string &room_id, SuccessCallback<const RoomAccessInfo&> success_cb, FailCallback fail_cb);
  //disconnect to calling room
  void Disconnect();
  //use to receiver RoomMessages
  void ConsumeRoomMessages();
  //use to deal sdp msg 
  void SendOfferSdp(const SDP &sdp);
  void SendAnswerSdp(const SDP &sdp);
  void SendLocalIceCandidate(const IceCandidate &ice_candidate);
  void SetRemoteSdpHandler(RemoteSdpHandler handler);
  void SetRemoteIceCandidateHandler(RemoteIceCandidateHandler handler);
  void SetRemoteByeHandler(RemoteByeHandler handler);
  const RoomAccessInfo& GetRoomAccessInfo();

 private:
  void HttpPostMessage(const std::string& path, SuccessCallback<const nlohmann::json&> success_cb, FailCallback fail_cb);
  void ConnectSignaling(const std::string &ws_url, SuccessCallback<> success_cb, FailCallback fail_cb);
  void OnSignalingConnected();
  void OnSignalingMessage(const std::string &message);
  void OnWebSocketMessage(const std::string &message);
  void HttpGetTurnServers(const std::string& url, SuccessCallback<const std::vector<IceServer>> success_cb, FailCallback fail_cb);
  void SendSignaling(const std::string &signaling);

  RemoteIceCandidateHandler remote_ice_candidate_handler_;
  RemoteSdpHandler remote_sdp_handler_;
  RemoteByeHandler remote_bye_handler_;
  
  std::string room_id_;
  std::string room_url_;
  RoomAccessInfo room_access_info_;
  ConnectionState connection_state_ = ConnectionState::Disconnected;
  std::vector<std::string> pending_signaling_list_;
  std::shared_ptr<rtc::Thread> thread_;
  std::shared_ptr<WebSocketClient> ws_client_;

};

}


#endif //WEBRTC_CLIENT__SIGNALING_CLIENT_H_
